/*****************************************************************************//*!
* file  : systask.c
* creat : apleilx
* note :  除初始化外，禁止该任务及其子程序使用含有阻塞的功能，包括数据存储，USB操作等等
* data  : 2019/07/02
*******************************************************************************/
#include "bsp.h"
#include "os_obj.h"
#include "systask.h"

#include "bsp_spi_nor.h"
#include "nor_cmd.h"

#include "common.h"

void spim_dmm_set(void);
void spim_init_set(void);

struct  
{
	uint8_t id[8];
	uint8_t *spim_buff;
	uint32_t spim_tm;	
} spim_o;



/*****************************************************************************
* @brief   storage task.
* @param   none
* @return  non
* @ Pass/ Fail criteria: none
*****************************************************************************/
void spim_opt(void)
{
	int addr, tmst;
	
	// spi模块的芯片识别兼容性较差
	// 外部先开QPI模式然后SPIM操作
	
	bsp_qpi_port_init();
	nor_spi_init();
    nor_init(1);
	
	// spi 初始化
	bsp_spim_port_init();

	spim_init_set();
	
	spim_o.spim_buff = malloc(4096+16);
	
	while (1)
	{
		if(sys_st.str_module != 4)
			break;
		
		spim_dmm_set();
		
		// 存储映射模式读全盘16MB约2870ms
		tmst = sys_st.ticks;
		
		for(addr = 0x8000000; addr < 0x8000000 + 16 * 1024 * 1024; addr += 4096 )
		{
			copy_u32((void *)addr, spim_o.spim_buff, 1024);
		}
		
		spim_o.spim_tm = sys_st.ticks - tmst;
		
		// 测试 DMA 读全盘16MB 约860ms
		tmst = sys_st.ticks;
		
		for(addr = 0; addr < 16 * 1024 * 1024; addr += 4096 )
		{
			SPIM_DMA_Read(addr, 0, 4096, spim_o.spim_buff, CMD_DMA_FAST_QUAD_READ, 1);
		}
		
		spim_o.spim_tm = sys_st.ticks - tmst;
		
		osDelay(2);
		NOP1();
	}
	
	free(spim_o.spim_buff);
}

/*****************************************************************************
* @brief   切换到存储映射读模式
* @param   none
* @return  non
* @ Pass/ Fail criteria: none
*****************************************************************************/
void spim_dmm_set(void)
{
	SPIM_DMM_ENABLE_BWEN();			// 使能突发模式
	
	// 直接存取模式
	SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_DIRECTMAP);
	// QPI读命令
	SPIM_SET_SPIM_MODE(CMD_DMA_FAST_QUAD_READ);
}

/*****************************************************************************
* @brief   初始配置
* @param   none
* @return  non
* @ Pass/ Fail criteria: none
*****************************************************************************/
void spim_init_set(void)
{
    SYS_UnlockReg();   

	// 基本模式
	SPIM_SET_OPMODE(SPIM_CTL0_OPMODE_IO);
	SPIM_DISABLE_CACHE();
	SPIM_ENABLE_CCM();
	
	// 设置时钟和读采样
	if(SystemCoreClock > 96000000)
	{
		SPIM_SET_CLOCK_DIVIDER(2);       

		SPIM_SET_RXCLKDLY_RDDLYSEL(0);
		SPIM_SET_RXCLKDLY_RDEDGE();
	}
	else
	{
		SPIM_SET_CLOCK_DIVIDER(1);

		SPIM_SET_RXCLKDLY_RDDLYSEL(0);
		SPIM_SET_RXCLKDLY_RDEDGE();
	}
	
	/* Set 4 dummy cycle. */
	SPIM_SET_DCNUM(4);
	SPIM_DMM_SET_DESELTIM(4);
	
	SYS_LockReg();
}
